import { Entity } from "../../../../../Core/Module/Entity/Entity";
import { EntitySceneFactory } from "../../../../../Core/Module/Entity/EntitySceneFactory";
import { Scene } from "../../../../../Core/Module/Entity/Scene";
import { SceneType } from "../../../../../Core/Module/Entity/SceneType";
import { IdGenerater } from "../../../../../Core/Module/IdGenerater/IdGenerater";
import { ETTask } from "../../../../../Support/Share/Lib/Async/ETTask";
import { StartSceneConfig } from "../../../../Model/Generate/Server/Config/StartSceneConfig";
import { BenchmarkClientComponent } from "../../../../Model/Server/Demo/Benchmark/BenchmarkClientComponent";
import { BenchmarkServerComponent } from "../../../../Model/Server/Demo/Benchmark/BenchmarkServerComponent";
import { GateSessionKeyComponent } from "../../../../Model/Server/Demo/Gate/GateSessionKeyComponent";
import { PlayerComponent } from "../../../../Model/Server/Demo/Gate/PlayerComponent";
import { RobotManagerComponent } from "../../../../Model/Server/Demo/Robot/RobotManagerComponent";
import { AOIManagerComponent } from "../../../../Model/Server/Module/AOI/AOIManagerComponent";
import { MailBoxComponent } from "../../../../Model/Server/Module/Actor/MailBoxComponent";
import { MailboxType } from "../../../../Model/Server/Module/Actor/MailboxType";
import { LocationComponent } from "../../../../Model/Server/Module/ActorLocation/LocationComponent";
import { HttpComponent } from "../../../../Model/Server/Module/Http/HttpComponent";
import { NetServerComponent } from "../../../../Model/Server/Module/Message/NetServerComponent";
import { UnitComponent } from "../../../../Model/Share/Module/Unit/UnitComponent";

export class SceneFactory {

    public static async Create(parent: Entity, name: string, sceneType: SceneType): Promise<Scene> {
        let instanceId = IdGenerater.Instance.GenerateInstanceId();
        return await this.CreateServerScene(parent, instanceId, instanceId, parent.DomainZone(), name, sceneType);
    }

    public static async CreateServerScene(parent: Entity, id: number, instanceId: number, zone: number, name: string, sceneType: SceneType, startSceneConfig: StartSceneConfig = null): Promise<Scene> {
        await ETTask.CompletedTask;

        let scene = EntitySceneFactory.CreateSceneWithId(id, instanceId, zone, sceneType, name, parent);

        scene.AddComponent<MailBoxComponent, MailboxType>(MailBoxComponent, MailboxType.UnOrderMessageDispatcher);

        switch (scene.SceneType) {
            case SceneType.RouterManager:
                // 正式发布请用CDN代替RouterManager
                // 云服务器在防火墙那里做端口映射
                scene.AddComponent<HttpComponent, string>(HttpComponent, `127.0.0.1:${startSceneConfig.OuterPort}`);
                break;
            case SceneType.Realm:
                scene.AddComponent<NetServerComponent, string>(NetServerComponent, startSceneConfig.InnerIPOutPort);
                break;
            case SceneType.Gate:
                scene.AddComponent<NetServerComponent, string>(NetServerComponent, startSceneConfig.InnerIPOutPort);
                scene.AddComponent<PlayerComponent>(PlayerComponent);
                scene.AddComponent<GateSessionKeyComponent>(GateSessionKeyComponent);
                break;
            case SceneType.Map:
                scene.AddComponent<UnitComponent>(UnitComponent);
                scene.AddComponent<AOIManagerComponent>(AOIManagerComponent);
                break;
            case SceneType.Location:
                scene.AddComponent<LocationComponent>(LocationComponent);
                break;
            case SceneType.Robot:
                scene.AddComponent<RobotManagerComponent>(RobotManagerComponent);
                break;
            case SceneType.BenchmarkServer:
                scene.AddComponent<BenchmarkServerComponent>(BenchmarkServerComponent);
                scene.AddComponent<NetServerComponent, string>(NetServerComponent, startSceneConfig.OuterIPPort);
                break;
            case SceneType.BenchmarkClient:
                scene.AddComponent<BenchmarkClientComponent>(BenchmarkClientComponent);
                break;
        }

        return scene;
    }

}